#ifndef GET_TYPE_HPP
#define GET_TYPE_HPP
#include <type_traits>
#include "exp_literal_types.hpp"
namespace exp_utilities
{
	namespace get_type_detail
	{
		template<class T, class U = std::void_t<>>
		struct get_type_impl : std::false_type
		{
			using type = literal_types::no_exist_type;
		};

		template<class T>
		struct get_type_impl<T, std::void_t<typename T::type>> : std::true_type
		{
			using type = typename T::type;
		};
	}
	template<class T>
	using get_type = typename get_type_detail::get_type_impl<T>::type;

	template<class T>
	constexpr bool has_type = get_type_detail::get_type_impl<T>::value;

	template<class T>
	concept has_value = requires{
		T::value;
	};
	template<class T, auto cmp>
	constexpr bool value_equal = false;

	template<class T, auto cmp> requires has_value<T>
	constexpr bool value_equal<T, cmp> = T::value == cmp;

	template<auto val>
	struct value_is {
		template<class T>
		struct apply : std::bool_constant<value_equal<T, val>> {
		};
		template<class F2>
		struct OR 
		{
			template<class T>
			struct apply : std::bool_constant<value_equal<T, val> || F2::template apply<T>::value> {};
		};
	};

	template<auto val>
	struct value_is_not {
		template<class T>
		struct apply : std::bool_constant<!value_equal<T, val>> {};
		template<class F2>
		struct OR
		{
			template<class T>
			struct apply : std::bool_constant<!(value_equal<T, val> || F2::template apply<T>::value)> {};
		};
	};
}

#endif // !GET_TYPE
